package com.evil.kingdom.handler;

import com.evil.kingdom.pojo.dto.alive.AliveMessage;
import com.evil.kingdom.pojo.dto.alive.AliveSuccess;
import com.evil.kingdom.pojo.dto.alive.SseEmitterUTF8;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * sse连接管理
 *
 * @author liyang
 * @date 2024-06-02 11:05
 */
@Slf4j
@Component
public class SseHandler {

    private final ConcurrentHashMap<String, CopyOnWriteArrayList<SseEmitterUTF8>> emitterMap = new ConcurrentHashMap<>();

    // region 新连接

    /**
     * 新连接-大世界
     *
     * @return SseEmitterUTF8
     */
    public SseEmitterUTF8 world() throws IOException {
        return this.addEmitterMap(this.worldEmitterMapKey());
    }

    /**
     * 新连接-战场
     *
     * @return SseEmitterUTF8
     */
    public SseEmitterUTF8 battlefield(String name) throws IOException {
        return this.addEmitterMap(this.battlefieldEmitterMapKey(name));
    }

    /**
     * 新连接
     *
     * @return SseEmitterUTF8
     */
    private SseEmitterUTF8 addEmitterMap(String key) throws IOException {
        SseEmitterUTF8 emitter = new SseEmitterUTF8(0L);
        emitter.send(new AliveMessage<>(new AliveSuccess("连接成功")));
        Runnable runnable = () -> {
            if (emitterMap.containsKey(key)) {
                CopyOnWriteArrayList<SseEmitterUTF8> emitters = emitterMap.get(key);
                emitters.remove(emitter);
            }
        };
        emitter.onCompletion(runnable);
        emitter.onTimeout(runnable);
        CopyOnWriteArrayList<SseEmitterUTF8> emitters = emitterMap.getOrDefault(key, new CopyOnWriteArrayList<>());
        emitters.add(emitter);
        emitterMap.put(key, emitters);
        return emitter;
    }
    // endregion

    // region 广播信息

    /**
     * 广播信息-大世界
     *
     * @param aliveMessage aliveMessage
     */
    public void sendWorld(AliveMessage<?> aliveMessage) {
        this.sendAll(this.worldEmitterMapKey(), aliveMessage);
    }

    /**
     * 广播信息-战场
     *
     * @param aliveMessage aliveMessage
     */
    public void sendBattlefield(String name, AliveMessage<?> aliveMessage) {
        this.sendAll(this.battlefieldEmitterMapKey(name), aliveMessage);
    }

    /**
     * 广播信息
     *
     * @param aliveMessage aliveMessage
     */
    private void sendAll(String key, AliveMessage<?> aliveMessage) {
        emitterMap.getOrDefault(key, new CopyOnWriteArrayList<>()).forEach(e -> {
            try {
                e.send(aliveMessage);
            } catch (Exception ex) {
                try {
                    e.complete();
                } catch (Exception ignored) {
                }
            }
        });
    }
    // endregion

    // region 连接key

    /**
     * 连接key-大世界
     *
     * @return String
     */
    private String worldEmitterMapKey() {
        return SseEmitterTypeEnum.WORLD.name();
    }

    /**
     * 连接key-战场
     *
     * @return String
     */
    private String battlefieldEmitterMapKey(String name) {
        return String.format("%s_%s", SseEmitterTypeEnum.BATTLEFIELD.name(), name);
    }
    // endregion

    /**
     * 会话类型
     */
    private enum SseEmitterTypeEnum {
        /**
         * 大世界
         */
        WORLD,
        /**
         * 战场
         */
        BATTLEFIELD,
        ;
    }
}
